const clear = require('clear')
const chalk = require('chalk')
const ora = require('ora')
const figlet = require('figlet')
const path = require('path')
const fs = require('fs')
const inquirer = require('inquirer')
const targetDirPath = process.env.PWD || process.cwd && process.cwd()
const { findTree, findPages, findSubpackages } = require('../util/fileTreeHelper')
const { buildPromptListTemplate, readFile, writeFile, runShell, ignoreJsonBuilder } = require('../util')
const { startDefaultValue } = require('../constant')

const appJsonTemplate = require('../template/app.json')
const envJsonTemplate = require('../template/env.config.json')
const sitemapJsonTemplate = require('../template/sitemap.json')
const projectJsonTemplate = require('../template/project.config.json')
const buildConfigJsonTemplate = require('../template/buildConfig.json')

module.exports = async (argv) => {

    // 定义变量
    const buildConf = {
        task: argv['t'] || argv['task'] || startDefaultValue.task,
        env: argv['e'] || argv['env'] || startDefaultValue.env,
    }
    typeof buildConf.task == 'boolean' ? buildConf.task = startDefaultValue.task : false
    typeof buildConf.env == 'boolean' ? buildConf.env = startDefaultValue.env : false
    const srcPath = path.resolve(targetDirPath, 'src'),
        // outputPath = path.resolve(targetDirPath, 'dist'),
        appJsonPath = path.resolve(targetDirPath, 'config/app.json'),
        envJsonPath = path.resolve(targetDirPath, 'config/env.config.json'),
        sitemapJsonPath = path.resolve(targetDirPath, 'config/sitemap.json'),
        projectJsonPath = path.resolve(targetDirPath, 'config/project.config.json'),
        distEnvJsPath = path.resolve(targetDirPath, 'dist/env.config.js'),
        distAppJsonPath = path.resolve(targetDirPath, 'dist/app.json'),
        distProjectJsonPath = path.resolve(targetDirPath, 'dist/project.config.json'),
        distSitemapJsonPath = path.resolve(targetDirPath, 'dist/sitemap.json'),
        buildIgnoreJsonPath = path.resolve(targetDirPath, 'temp/buildIgnore.json'),
        buildConfigJsonPath = path.resolve(targetDirPath, 'config/buildConfig.json'),
        gulpFilePath = path.resolve(targetDirPath, 'gulpfile.js'),
        gulpFileTemplatePath = path.resolve(__dirname, '../template/gulpfile.js'),
        taskName = buildConf.task
    let srcTree,        // 目录树
        pages,          // 目录树app.json里的pages
        subpackages,    // 目录树app.json里的subpackages
        promptList,     // 选择选项
        answers,        // 选择后的选项,包括: pages,subpackages
        appJson,        // 最终输出的app.json
        envJson,        // 最终输出的env.config.js
        sitemapJson,    // 最终输出的sitemap.json
        projectJson,    // 最终输出的project.config.json
        ignorePages,    // 排除的pages
        ignoreSubpackage,   // 排除的subpackage
        ignoreJsonStr,  //  排除输出json
        buildConfigJson // 编译时的配置文件

    // 清屏
    clear()
    // 打印启动信息
    console.log(figlet.textSync('weapp-cli'))
    console.log(chalk.yellow('task:'), buildConf.task)
    console.log(chalk.yellow('env:'), buildConf.env)

    // 读配置文件
    if (!fs.existsSync(buildConfigJsonPath)) {
        buildConfigJson = buildConfigJsonTemplate
    } else {
        buildConfigJson = Object.assign(buildConfigJsonTemplate, readFile(buildConfigJsonPath, true))
    }

    // loading, 分析文件树
    const spinner = ora()
    spinner.start(chalk.green('分析文件目录'))
    srcTree = findTree(srcPath)
    pages = findPages(srcTree, buildConfigJson)
    subpackages = findSubpackages(srcTree, buildConfigJson)
    spinner.succeed(chalk.green('分析文件目录完毕'))

    // 选择选项
    if (buildConf.env == 'prod') {
        answers = {
            pages,
            subpackages: subpackages.map(v => { return v.root })
        }
    } else {
        promptList = buildPromptListTemplate(pages, subpackages)
        answers = await inquirer.prompt(promptList)
    }


    // 清空dist
    spinner.start(chalk.green('清空dist'))
    await runShell('gulp', ['clean'])
        .then(res => {
            return true
        })
        .catch(err => {
            spinner.fail(chalk.red('执行失败:'), err)
            return false
        })
    spinner.succeed(chalk.green('清空dist完毕'))

    // 读模板文件
    spinner.start(chalk.green('读模板文件'))
    envJson = envJsonTemplate
    if (fs.existsSync(envJsonPath)) {
        envJson = Object.assign(envJson, readFile(envJsonPath, true))
    }
    envJson.result = envJson[buildConf.env] || envJson['prod'] || {}

    projectJson = projectJsonTemplate
    if (fs.existsSync(projectJsonPath)) {
        projectJson = Object.assign(projectJson, readFile(projectJsonPath, true))
    }
    if (fs.existsSync(distProjectJsonPath)) {
        projectJson = Object.assign(projectJson, readFile(distProjectJsonPath, true))
    }

    sitemapJson = sitemapJsonTemplate
    if (fs.existsSync(sitemapJsonPath)) {
        sitemapJson = Object.assign(sitemapJson, readFile(sitemapJsonPath, true))
    }

    appJson = appJsonTemplate
    if (fs.existsSync(appJsonPath)) {
        appJson = Object.assign(appJson, readFile(appJsonPath, true))
    }
    appJson.pages = Object.assign(appJson.pages, answers.pages)
    appJson.subpackages = Object.assign(appJson.subpackages, subpackages.filter(s => { return answers.subpackages.includes(s.root) }))
    ignorePages = pages.filter(p => { return !answers.pages.includes(p) })
    ignoreSubpackage = subpackages.map(subObj => { return subObj.root }).filter(s => { return !answers.subpackages.includes(s) })
    ignoreJsonStr = ignoreJsonBuilder(ignorePages, ignoreSubpackage)
    spinner.succeed(chalk.green('读模板文件完毕'))

    // 写模板文件
    spinner.start(chalk.green('写模板文件'))
    writeFile(distEnvJsPath, `module.exports = ${JSON.stringify(envJson.result, null, '\t')}`)
    writeFile(distProjectJsonPath, JSON.stringify(projectJson, null, '\t'))
    writeFile(distSitemapJsonPath, JSON.stringify(sitemapJson, null, '\t'))
    writeFile(distAppJsonPath, JSON.stringify(appJson, null, '\t'))
    writeFile(buildIgnoreJsonPath, JSON.stringify(ignoreJsonStr, null, '\t'))
    spinner.succeed(chalk.green('写模板文件完毕'))

    // 检查gulp
    if (!fs.existsSync(gulpFilePath)) {
        writeFile(gulpFilePath, readFile(gulpFileTemplatePath))
    }

    // 开始编译
    spinner.start(chalk.green('开始编译'))
    if (buildConf.task == 'watch') {
        spinner.text = '监听文件修改...'
    }
    await runShell('gulp', [taskName], true)
        .then(res => {
            return true
        })
        .catch(err => {
            spinner.fail(chalk.red('执行失败:'), err)
            return false
        })
    spinner.succeed(chalk.green('执行完毕'))

}